﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using RuoVea.ExConfig;
using RuoVea.ExJwtBearer;
using RuoVea.ExPws;
using RuoVea.ExPws.Options;
using RuoVea.OmiApi.Config;
using RuoVea.OmiApi.UserRole.SeedData;
using RuoVea.OmiApi.UserRole.Service;

namespace RuoVea.OmiApi.UserRole;

/// <summary>
/// 注入扩展
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 用户角色管理
    /// </summary>
    /// <param name="services"></param>
    /// <param name="serviceLifetime">Scoped</param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static IServiceCollection AddOmiSystemSetup(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
    {
        if (services == null) throw new ArgumentNullException(nameof(services));
        services.Configure<DbInitConfig>(AppSettings.Configuration.GetSection("DbInitConfig"));
        return DI(services, null, serviceLifetime);
    }

    /// <summary>
    /// 用户角色管理
    /// </summary>
    /// <param name="services"></param>
    /// <param name="config"></param>
    /// <param name="serviceLifetime">Scoped</param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static IServiceCollection AddOmiSystemSetup(this IServiceCollection services, IConfiguration config, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
    {
        if (services == null) throw new ArgumentNullException(nameof(services));
        if (config == null) throw new ArgumentNullException(nameof(config));
        services.Configure<DbInitConfig>(config);
        DbInitConfig dbInitConfig = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
        return DI(services, dbInitConfig, serviceLifetime);
    }

    /// <summary>
    /// 用户角色管理
    /// </summary>
    /// <param name="services"></param>
    /// <param name="config"></param>
    /// <param name="serviceLifetime">Scoped</param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static IServiceCollection AddOmiSystemSetup(this IServiceCollection services, Action<DbInitConfig> config, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
    {
        if (services == null) throw new ArgumentNullException(nameof(services));
        if (config == null) throw new ArgumentNullException(nameof(config));
        services.Configure(config);
        DbInitConfig dbInitConfig = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
        return DI(services, dbInitConfig, serviceLifetime);
    }

    #region DI
    private static IServiceCollection DI(IServiceCollection services, DbInitConfig dbInitConfig, ServiceLifetime serviceLifetime)
    {
        services.AddJwtSetup();
        services.Configure<PasswordConfig>(AppSettings.Configuration.GetSection("PasswordConfig"));
        //services.AddCaptcha(AppSettings.Configuration);

        switch (serviceLifetime)
        {
            case ServiceLifetime.Scoped:
                services.AddScoped<SysCacheService>();
                services.AddScoped<SysRoleService>();
                services.AddScoped<SysRoleService>();
                services.AddScoped<SysUserRoleService>();
                services.AddScoped<SysUserService>();
                services.AddScoped<IPasswordServer>();
                break;
            case ServiceLifetime.Singleton:
                services.AddSingleton<SysCacheService>();
                services.AddSingleton<SysRoleService>();
                services.AddSingleton<SysRoleService>();
                services.AddSingleton<SysUserRoleService>();
                services.AddSingleton<SysUserService>();
                services.AddSingleton<IPasswordServer>();
                break;
            case ServiceLifetime.Transient:
                services.AddTransient<SysCacheService>();
                services.AddTransient<SysRoleService>();
                services.AddTransient<SysRoleService>();
                services.AddTransient<SysUserRoleService>();
                services.AddTransient<SysUserService>();
                services.AddTransient<IPasswordServer>();
                break;
        }
        services.AddOmiConfigSetup((o) => { o = dbInitConfig; }, serviceLifetime);
        return services;
    }
    #endregion

    /// <summary>
    /// 用户角色管理 - 初始化数据库/初始化种子数据
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public static IServiceCollection AddSystemInitSetup(this IServiceCollection services)
    {
        Task.Run(() =>
        {
            services.AddConfigInitSetup();
            DbInitConfig config = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
            var _thisRepository = services.BuildServiceProvider().GetRequiredService<ISqlSugarClient>();
            if (config.InitTable && _thisRepository != null)
            {

                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysRole), false) || _thisRepository.DbMaintenance.IsAnyTable("sys_role", false)) { }else
                {
                    _thisRepository.CodeFirst.InitTables<SysRole>();
                    if (config.InitSeedData)
                        _thisRepository.Storageable(new SysRole_SeedData().HasData().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                }


                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysUser), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_user", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysUser>();
                    if (config.InitSeedData)
                    {
                        PasswordConfig passwordConfig = services.BuildServiceProvider().GetRequiredService<IOptions<PasswordConfig>>()?.Value;
                        IPasswordServer passwordServer = services.BuildServiceProvider().GetRequiredService<IPasswordServer>();
                        var seedData = new SysUser_SeedData().HasData().ToList();
                        string defaultEncryptPassword = passwordServer.Encrypt(passwordConfig.DefaultPassword);
                        seedData.ForEach(x => x.Password = defaultEncryptPassword);
                        _thisRepository.Storageable(seedData).ToStorage().AsInsertable.ExecuteCommand();
                    }
                }
                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysUserRole), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_user_role", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysUserRole>();
                    if (config.InitSeedData)
                        _thisRepository.Storageable(new SysUserRole_SeedData().HasData().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                }
             
            }
        });
        return services;
    }
}
